<template>
  <render-form />
</template>

<script setup>
  import { h, ref } from 'vue'
  import { ElInput, ElForm, ElFormItem, ElCheckbox, ElButton, ElSelect, ElOption } from 'element-plus'

  const props = defineProps({
    fields: {
      type: Array,
      default: () => []
    },
    model: {
      type: Object,
      default: () => ({})
    },
    rules: {
      type: Array,
      default: () => []
    }
  })
  const changeEvent = item => {
    props.model.setVal(item.target, getValue(props.model, item.target))
    item.change && item.change(props.model[item.target])
  }

  const setValue = (obj, target, val) => {
    if (obj[target] === undefined) {
      return
    }
    if (obj[target].value === undefined) {
      obj[target] = val
    } else {
      obj[target].value = val
    }
  }

  const getValue = (obj, target) => {
    if (obj[target] === undefined) {
      return
    }
    if (obj[target].value === undefined) {
      return obj[target]
    } else {
      return obj[target].value
    }
  }

  const generateCurrent = (h, field) => {
    if (field.isCheckbox) {
      return h(ElCheckbox, {
        modelValue: getValue(props.model, field.target),
        disabled: field.disabled,
        'onUpdate:modelValue'(val) {
          setValue(props.model, field.target, val)
        },
        onChange: () => changeEvent(field),
        label: '启用'
      })
    } else if (field.isSelect) {
      return h(
        ElSelect,
        {
          modelValue: getValue(props.model, field.target),
          disabled: field.disabled,
          'onUpdate:modelValue'(val) {
            setValue(props.model, field.target, val)
          },
          onChange: () => changeEvent(field),
        },
        {
          default: () => {
            return field.options.map(op => {
              return h(ElOption, {
                key: op.value || op,
                value: op.value || op,
                label: op.label || op
              })
            })
          },
          append: () => {
            return field.appendBtnText
              ? h(
                  ElButton,
                  {
                    onClick: () => field.clickEvent
                  },
                  [field.appendBtnText]
                )
              : ''
          }
        }
      )
    } else {
      return h(
        ElInput,
        {
          modelValue: getValue(props.model, field.target),
          disabled: field.disabled,
          'onUpdate:modelValue'(val) {
            setValue(props.model, field.target, val)
          },
          onChange: () => changeEvent(field),
          type: 'number',
          class: 'input-with-select'
        },
        {
          append: () => {
            if (field.appendSelect) {
              return h(
                ElSelect,
                {
                  style: {
                    width: '80px'
                  },
                  disabled: field.disabled,
                  modelValue: props.model[field.target]?.unit,
                  'onUpdate:modelValue'(val) {
                    const item = props.model[field.target]
                    if (!item) {
                      return
                    }
                    item.unit = val
                  },
                  onChange: () => changeEvent(field)
                },
                field.options.map(op => {
                  return h(ElOption, {
                    key: op.value || op,
                    value: op.value || op,
                    label: op.label || op
                  })
                })
              )
            } else if (field.appendBtnText) {
              return h(
                ElButton,
                {
                  onClick: field.clickEvent
                },
                [field.appendBtnText]
              )
            } else if (field.appendText) {
              return h(
                'span',
                {},
                [field.appendText]
              )
            }
          }
        }
      )
    }
  }

  const renderForm = {
    render: () => {
      return h(
        ElForm,
        {
          rules: props.rules
        },
        props.fields.map(field => {
          return h(
            ElFormItem,
            {
              key: field.name,
              label: field.name
            },
            [generateCurrent(h, field)]
          )
        })
      )
    }
  }
</script>

<style scoped lang="scss">
  :deep(.el-form-item__label) {
    min-width: 100px;
    justify-content: flex-start;
    font-weight: 400;
  }

  :deep(.el-input-group__append) {
    padding: 0;

    & > * {
      margin: 0
    }
    > span {
      padding: 0 12px;
      display: inline-block;
      width: 80px
    }
  }
</style>
